Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


visualiser-wasm/internal/layout/force.go 68e6d65c5371c3bd2c85be20f9286a0b4fffdc3d (68e6d65c) Text, 5.99 KB

T8b949e// SPDX-License-Identifier: 0BSD

T8b949e// Package layout settles node positions with a fast force simulation.
T8b949e// Runs in WASM so vis-network can keep its JS physics solver off
T8b949e// (that solver is the main FPS bottleneck for large graphs).
Tff7b72package Te6edf3layout

Tff7b72import Tb4b4b4(
Ta5d6ff"math"
Tb4b4b4)

T8b949e// Node is one body in the layout simulation.
Tff7b72type Te6edf3Node Tff7b72struct Tb4b4b4{
Te6edf3ID Tffa657string Ta5d6ff`json:"id"`
Te6edf3X Tffa657float64 Ta5d6ff`json:"x"`
Te6edf3Y Tffa657float64 Ta5d6ff`json:"y"`
Te6edf3Vx Tffa657float64 Ta5d6ff`json:"vx"`
Te6edf3Vy Tffa657float64 Ta5d6ff`json:"vy"`
Te6edf3Mass Tffa657float64 Ta5d6ff`json:"mass"`
Te6edf3Fixed Tffa657bool Ta5d6ff`json:"fixed"`
Tb4b4b4}

T8b949e// Edge is a spring between two node ids.
Tff7b72type Te6edf3Edge Tff7b72struct Tb4b4b4{
Te6edf3From Tffa657string Ta5d6ff`json:"from"`
Te6edf3To Tffa657string Ta5d6ff`json:"to"`
Te6edf3Length Tffa657float64 Ta5d6ff`json:"length"`
Tb4b4b4}

T8b949e// Request configures a layout settle pass.
Tff7b72type Te6edf3Request Tff7b72struct Tb4b4b4{
Te6edf3Nodes Tb4b4b4[Tb4b4b4]Te6edf3Node Ta5d6ff`json:"nodes"`
Te6edf3Edges Tb4b4b4[Tb4b4b4]Te6edf3Edge Ta5d6ff`json:"edges"`
Te6edf3Iterations Tffa657int Ta5d6ff`json:"iterations"`
Te6edf3Gravity Tffa657float64 Ta5d6ff`json:"gravity"`
Te6edf3Repulsion Tffa657float64 Ta5d6ff`json:"repulsion"`
Te6edf3SpringK Tffa657float64 Ta5d6ff`json:"spring_k"`
Te6edf3Damping Tffa657float64 Ta5d6ff`json:"damping"`
Te6edf3MaxSpeed Tffa657float64 Ta5d6ff`json:"max_speed"`
Tb4b4b4}

T8b949e// Result is settled positions keyed by node id.
Tff7b72type Te6edf3Result Tff7b72struct Tb4b4b4{
Te6edf3Positions Tff7b72mapTb4b4b4[Tffa657stringTb4b4b4]Te6edf3XY Ta5d6ff`json:"positions"`
Te6edf3Iterations Tffa657int Ta5d6ff`json:"iterations"`
Tb4b4b4}

T8b949e// XY is a 2D point.
Tff7b72type Te6edf3XY Tff7b72struct Tb4b4b4{
Te6edf3X Tffa657float64 Ta5d6ff`json:"x"`
Te6edf3Y Tffa657float64 Ta5d6ff`json:"y"`
Tb4b4b4}

Tff7b72type Te6edf3body Tff7b72struct Tb4b4b4{
Te6edf3id Tffa657string
Te6edf3xTb4b4b4, Te6edf3y Tffa657float64
Te6edf3vxTb4b4b4, Te6edf3vy Tffa657float64
Te6edf3mass Tffa657float64
Te6edf3fixed Tffa657bool
Tb4b4b4}

T8b949e// Settle runs a damped spring + grid-repulsion layout in-place.
Tff7b72func Te6edf3SettleTb4b4b4(Te6edf3req Te6edf3RequestTb4b4b4) Te6edf3Result Tb4b4b4{
Te6edf3n Tff7b72:= Tffa657lenTb4b4b4(Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4)
Te6edf3out Tff7b72:= Te6edf3ResultTb4b4b4{Te6edf3PositionsTb4b4b4: Tffa657makeTb4b4b4(Tff7b72mapTb4b4b4[Tffa657stringTb4b4b4]Te6edf3XYTb4b4b4, Te6edf3nTb4b4b4)Tb4b4b4}
Tff7b72if Te6edf3n Tff7b72== T79c0ff0 Tb4b4b4{
Tff7b72return Te6edf3out
Tb4b4b4}

Te6edf3iters Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3Iterations
Tff7b72if Te6edf3iters Tff7b72<= T79c0ff0 Tb4b4b4{
Te6edf3iters Tb4b4b4= Te6edf3pickIterationsTb4b4b4(Te6edf3nTb4b4b4)
Tb4b4b4}
Tff7b72if Te6edf3iters Tb4b4b4> T79c0ff400 Tb4b4b4{
Te6edf3iters Tb4b4b4= T79c0ff400
Tb4b4b4}

Te6edf3gravity Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3Gravity
T8b949e// Negative gravity means "off" (live Tick). Zero means use the default
T8b949e// centering pull for one-shot settle. Live layout must not vacuum nodes
T8b949e// toward the origin or users cannot shape the graph.
Tff7b72if Te6edf3gravity Tb4b4b4< T79c0ff0 Tb4b4b4{
Te6edf3gravity Tb4b4b4= T79c0ff0
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3gravity Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3gravity Tb4b4b4= T79c0ff0.01
Tb4b4b4}
Te6edf3repulsion Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3Repulsion
Tff7b72if Te6edf3repulsion Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3repulsion Tb4b4b4= T79c0ff1800
Tb4b4b4}
Te6edf3springK Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3SpringK
Tff7b72if Te6edf3springK Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3springK Tb4b4b4= T79c0ff0.032
Tb4b4b4}
Te6edf3damping Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3Damping
Tff7b72if Te6edf3damping Tff7b72== T79c0ff0 Tb4b4b4{
T8b949e// Multiply kept velocity each step. Lower = more friction, less twitch.
Te6edf3damping Tb4b4b4= T79c0ff0.68
Tb4b4b4}
Te6edf3maxSpeed Tff7b72:= Te6edf3reqTb4b4b4.Te6edf3MaxSpeed
Tff7b72if Te6edf3maxSpeed Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3maxSpeed Tb4b4b4= T79c0ff18
Tb4b4b4}

Te6edf3bodies Tff7b72:= Tffa657makeTb4b4b4(Tb4b4b4[Tb4b4b4]Te6edf3bodyTb4b4b4, Te6edf3nTb4b4b4)
Te6edf3index Tff7b72:= Tffa657makeTb4b4b4(Tff7b72mapTb4b4b4[Tffa657stringTb4b4b4]Tffa657intTb4b4b4, Te6edf3nTb4b4b4)
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3reqTb4b4b4.Te6edf3Nodes Tb4b4b4{
Te6edf3nd Tff7b72:= Tff7b72&Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4[Te6edf3iTb4b4b4]
Te6edf3mass Tff7b72:= Te6edf3ndTb4b4b4.Te6edf3Mass
Tff7b72if Te6edf3mass Tff7b72<= T79c0ff0 Tb4b4b4{
Te6edf3mass Tb4b4b4= T79c0ff1
Tb4b4b4}
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4] Tb4b4b4= Te6edf3bodyTb4b4b4{
Te6edf3idTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3IDTb4b4b4,
Te6edf3xTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3XTb4b4b4,
Te6edf3yTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3YTb4b4b4,
Te6edf3vxTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3VxTb4b4b4,
Te6edf3vyTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3VyTb4b4b4,
Te6edf3massTb4b4b4: Te6edf3massTb4b4b4,
Te6edf3fixedTb4b4b4: Te6edf3ndTb4b4b4.Te6edf3Fixed Tff7b72|| Te6edf3ndTb4b4b4.Te6edf3ID Tff7b72== Ta5d6ff"me"Tb4b4b4,
Tb4b4b4}
Te6edf3indexTb4b4b4[Te6edf3ndTb4b4b4.Te6edf3IDTb4b4b4] Tb4b4b4= Te6edf3i
Tb4b4b4}

Tff7b72type Te6edf3spring Tff7b72struct Tb4b4b4{
Te6edf3aTb4b4b4, Te6edf3b Tffa657int
Te6edf3len Tffa657float64
Tb4b4b4}
Te6edf3springs Tff7b72:= Tffa657makeTb4b4b4(Tb4b4b4[Tb4b4b4]Te6edf3springTb4b4b4, T79c0ff0Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3reqTb4b4b4.Te6edf3EdgesTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3reqTb4b4b4.Te6edf3Edges Tb4b4b4{
Te6edf3e Tff7b72:= Tff7b72&Te6edf3reqTb4b4b4.Te6edf3EdgesTb4b4b4[Te6edf3iTb4b4b4]
Te6edf3aiTb4b4b4, Te6edf3okA Tff7b72:= Te6edf3indexTb4b4b4[Te6edf3eTb4b4b4.Te6edf3FromTb4b4b4]
Te6edf3biTb4b4b4, Te6edf3okB Tff7b72:= Te6edf3indexTb4b4b4[Te6edf3eTb4b4b4.Te6edf3ToTb4b4b4]
Tff7b72if Tb4b4b4!Te6edf3okA Tff7b72|| Tb4b4b4!Te6edf3okB Tff7b72|| Te6edf3ai Tff7b72== Te6edf3bi Tb4b4b4{
Tff7b72continue
Tb4b4b4}
Te6edf3length Tff7b72:= Te6edf3eTb4b4b4.Te6edf3Length
Tff7b72if Te6edf3length Tff7b72<= T79c0ff0 Tb4b4b4{
Te6edf3length Tb4b4b4= T79c0ff280
Tb4b4b4}
Te6edf3springs Tb4b4b4= Tffa657appendTb4b4b4(Te6edf3springsTb4b4b4, Te6edf3springTb4b4b4{Te6edf3aTb4b4b4: Te6edf3aiTb4b4b4, Te6edf3bTb4b4b4: Te6edf3biTb4b4b4, Te6edf3lenTb4b4b4: Te6edf3lengthTb4b4b4}Tb4b4b4)
Tb4b4b4}

Te6edf3cellSize Tff7b72:= T79c0ff220.0
Tff7b72for Te6edf3step Tff7b72:= T79c0ff0Tb4b4b4; Te6edf3step Tb4b4b4< Te6edf3itersTb4b4b4; Te6edf3stepTff7b72++ Tb4b4b4{
Te6edf3fx Tff7b72:= Tffa657makeTb4b4b4(Tb4b4b4[Tb4b4b4]Tffa657float64Tb4b4b4, Te6edf3nTb4b4b4)
Te6edf3fy Tff7b72:= Tffa657makeTb4b4b4(Tb4b4b4[Tb4b4b4]Tffa657float64Tb4b4b4, Te6edf3nTb4b4b4)

T8b949e// Weak pull toward origin keeps the mesh centred.
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3bodies Tb4b4b4{
Tff7b72if Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3fixed Tb4b4b4{
Tff7b72continue
Tb4b4b4}
Te6edf3fxTb4b4b4[Te6edf3iTb4b4b4] Tff7b72-= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x Tff7b72* Te6edf3gravity Tff7b72* Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3mass
Te6edf3fyTb4b4b4[Te6edf3iTb4b4b4] Tff7b72-= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y Tff7b72* Te6edf3gravity Tff7b72* Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3mass
Tb4b4b4}

T8b949e// Grid-bucketed repulsion (near O(n) average).
Te6edf3buckets Tff7b72:= Tffa657makeTb4b4b4(Tff7b72mapTb4b4b4[Tb4b4b4[T79c0ff2Tb4b4b4]Tffa657intTb4b4b4]Tb4b4b4[Tb4b4b4]Tffa657intTb4b4b4, Te6edf3nTff7b72/T79c0ff2Tff7b72+T79c0ff1Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3bodies Tb4b4b4{
Te6edf3cx Tff7b72:= Tffa657intTb4b4b4(Te6edf3mathTb4b4b4.Te6edf3FloorTb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x Tff7b72/ Te6edf3cellSizeTb4b4b4)Tb4b4b4)
Te6edf3cy Tff7b72:= Tffa657intTb4b4b4(Te6edf3mathTb4b4b4.Te6edf3FloorTb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y Tff7b72/ Te6edf3cellSizeTb4b4b4)Tb4b4b4)
Te6edf3key Tff7b72:= Tb4b4b4[T79c0ff2Tb4b4b4]Tffa657intTb4b4b4{Te6edf3cxTb4b4b4, Te6edf3cyTb4b4b4}
Te6edf3bucketsTb4b4b4[Te6edf3keyTb4b4b4] Tb4b4b4= Tffa657appendTb4b4b4(Te6edf3bucketsTb4b4b4[Te6edf3keyTb4b4b4]Tb4b4b4, Te6edf3iTb4b4b4)
Tb4b4b4}
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3bodies Tb4b4b4{
Tff7b72if Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3fixed Tb4b4b4{
Tff7b72continue
Tb4b4b4}
Te6edf3cx Tff7b72:= Tffa657intTb4b4b4(Te6edf3mathTb4b4b4.Te6edf3FloorTb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x Tff7b72/ Te6edf3cellSizeTb4b4b4)Tb4b4b4)
Te6edf3cy Tff7b72:= Tffa657intTb4b4b4(Te6edf3mathTb4b4b4.Te6edf3FloorTb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y Tff7b72/ Te6edf3cellSizeTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3dx Tff7b72:= Tff7b72-T79c0ff1Tb4b4b4; Te6edf3dx Tff7b72<= T79c0ff1Tb4b4b4; Te6edf3dxTff7b72++ Tb4b4b4{
Tff7b72for Te6edf3dy Tff7b72:= Tff7b72-T79c0ff1Tb4b4b4; Te6edf3dy Tff7b72<= T79c0ff1Tb4b4b4; Te6edf3dyTff7b72++ Tb4b4b4{
Te6edf3list Tff7b72:= Te6edf3bucketsTb4b4b4[Tb4b4b4[T79c0ff2Tb4b4b4]Tffa657intTb4b4b4{Te6edf3cx Tff7b72+ Te6edf3dxTb4b4b4, Te6edf3cy Tff7b72+ Te6edf3dyTb4b4b4}Tb4b4b4]
Tff7b72for Te6edf3_Tb4b4b4, Te6edf3j Tff7b72:= Tff7b72range Te6edf3list Tb4b4b4{
Tff7b72if Te6edf3j Tff7b72<= Te6edf3i Tb4b4b4{
Tff7b72continue
Tb4b4b4}
Te6edf3dxp Tff7b72:= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x Tff7b72- Te6edf3bodiesTb4b4b4[Te6edf3jTb4b4b4]Tb4b4b4.Te6edf3x
Te6edf3dyp Tff7b72:= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y Tff7b72- Te6edf3bodiesTb4b4b4[Te6edf3jTb4b4b4]Tb4b4b4.Te6edf3y
Te6edf3dist2 Tff7b72:= Te6edf3dxpTff7b72*Te6edf3dxp Tff7b72+ Te6edf3dypTff7b72*Te6edf3dyp Tff7b72+ T79c0ff0.01
Te6edf3inv Tff7b72:= T79c0ff1.0 Tff7b72/ Te6edf3mathTb4b4b4.Te6edf3SqrtTb4b4b4(Te6edf3dist2Tb4b4b4)
Te6edf3force Tff7b72:= Te6edf3repulsion Tff7b72* Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3mass Tff7b72* Te6edf3bodiesTb4b4b4[Te6edf3jTb4b4b4]Tb4b4b4.Te6edf3mass Tff7b72* Te6edf3inv Tff7b72* Te6edf3inv
Te6edf3fxTb4b4b4[Te6edf3iTb4b4b4] Tff7b72+= Te6edf3dxp Tff7b72* Te6edf3inv Tff7b72* Te6edf3force
Te6edf3fyTb4b4b4[Te6edf3iTb4b4b4] Tff7b72+= Te6edf3dyp Tff7b72* Te6edf3inv Tff7b72* Te6edf3force
Tff7b72if Tb4b4b4!Te6edf3bodiesTb4b4b4[Te6edf3jTb4b4b4]Tb4b4b4.Te6edf3fixed Tb4b4b4{
Te6edf3fxTb4b4b4[Te6edf3jTb4b4b4] Tff7b72-= Te6edf3dxp Tff7b72* Te6edf3inv Tff7b72* Te6edf3force
Te6edf3fyTb4b4b4[Te6edf3jTb4b4b4] Tff7b72-= Te6edf3dyp Tff7b72* Te6edf3inv Tff7b72* Te6edf3force
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// Springs
Tff7b72for Te6edf3_Tb4b4b4, Te6edf3s Tff7b72:= Tff7b72range Te6edf3springs Tb4b4b4{
Te6edf3a Tff7b72:= Tff7b72&Te6edf3bodiesTb4b4b4[Te6edf3sTb4b4b4.Te6edf3aTb4b4b4]
Te6edf3b Tff7b72:= Tff7b72&Te6edf3bodiesTb4b4b4[Te6edf3sTb4b4b4.Te6edf3bTb4b4b4]
Te6edf3dxp Tff7b72:= Te6edf3bTb4b4b4.Te6edf3x Tff7b72- Te6edf3aTb4b4b4.Te6edf3x
Te6edf3dyp Tff7b72:= Te6edf3bTb4b4b4.Te6edf3y Tff7b72- Te6edf3aTb4b4b4.Te6edf3y
Te6edf3dist Tff7b72:= Te6edf3mathTb4b4b4.Te6edf3SqrtTb4b4b4(Te6edf3dxpTff7b72*Te6edf3dxp Tff7b72+ Te6edf3dypTff7b72*Te6edf3dypTb4b4b4)
Tff7b72if Te6edf3dist Tb4b4b4< T79c0ff0.01 Tb4b4b4{
Te6edf3dist Tb4b4b4= T79c0ff0.01
Tb4b4b4}
Te6edf3delta Tff7b72:= Te6edf3dist Tff7b72- Te6edf3sTb4b4b4.Te6edf3len
Te6edf3force Tff7b72:= Te6edf3springK Tff7b72* Te6edf3delta
Te6edf3ux Tff7b72:= Te6edf3dxp Tff7b72/ Te6edf3dist
Te6edf3uy Tff7b72:= Te6edf3dyp Tff7b72/ Te6edf3dist
Tff7b72if Tb4b4b4!Te6edf3aTb4b4b4.Te6edf3fixed Tb4b4b4{
Te6edf3fxTb4b4b4[Te6edf3sTb4b4b4.Te6edf3aTb4b4b4] Tff7b72+= Te6edf3ux Tff7b72* Te6edf3force
Te6edf3fyTb4b4b4[Te6edf3sTb4b4b4.Te6edf3aTb4b4b4] Tff7b72+= Te6edf3uy Tff7b72* Te6edf3force
Tb4b4b4}
Tff7b72if Tb4b4b4!Te6edf3bTb4b4b4.Te6edf3fixed Tb4b4b4{
Te6edf3fxTb4b4b4[Te6edf3sTb4b4b4.Te6edf3bTb4b4b4] Tff7b72-= Te6edf3ux Tff7b72* Te6edf3force
Te6edf3fyTb4b4b4[Te6edf3sTb4b4b4.Te6edf3bTb4b4b4] Tff7b72-= Te6edf3uy Tff7b72* Te6edf3force
Tb4b4b4}
Tb4b4b4}

T8b949e// Integrate
Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3bodies Tb4b4b4{
Tff7b72if Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3fixed Tb4b4b4{
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx Tb4b4b4= T79c0ff0
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy Tb4b4b4= T79c0ff0
Tff7b72continue
Tb4b4b4}
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx Tb4b4b4= Tb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx Tff7b72+ Te6edf3fxTb4b4b4[Te6edf3iTb4b4b4]Tff7b72/Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3massTb4b4b4) Tff7b72* Te6edf3damping
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy Tb4b4b4= Tb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy Tff7b72+ Te6edf3fyTb4b4b4[Te6edf3iTb4b4b4]Tff7b72/Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3massTb4b4b4) Tff7b72* Te6edf3damping
Te6edf3speed Tff7b72:= Te6edf3mathTb4b4b4.Te6edf3HypotTb4b4b4(Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vxTb4b4b4, Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vyTb4b4b4)
Tff7b72if Te6edf3speed Tb4b4b4> Te6edf3maxSpeed Tb4b4b4{
Te6edf3scale Tff7b72:= Te6edf3maxSpeed Tff7b72/ Te6edf3speed
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx Tff7b72*= Te6edf3scale
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy Tff7b72*= Te6edf3scale
Tb4b4b4}
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x Tff7b72+= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx
Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y Tff7b72+= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy
Tb4b4b4}
Tb4b4b4}

Tff7b72for Te6edf3i Tff7b72:= Tff7b72range Te6edf3bodies Tb4b4b4{
Te6edf3outTb4b4b4.Te6edf3PositionsTb4b4b4[Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3idTb4b4b4] Tb4b4b4= Te6edf3XYTb4b4b4{Te6edf3XTb4b4b4: Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3xTb4b4b4, Te6edf3YTb4b4b4: Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3yTb4b4b4}
T8b949e// Write velocities back onto the request nodes when ids match so
T8b949e// live layout can carry momentum across Tick frames.
Tff7b72if Te6edf3idxTb4b4b4, Te6edf3ok Tff7b72:= Te6edf3indexTb4b4b4[Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4; Te6edf3ok Tb4b4b4{
Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3X Tb4b4b4= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3x
Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3Y Tb4b4b4= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3y
Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3Vx Tb4b4b4= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vx
Te6edf3reqTb4b4b4.Te6edf3NodesTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3Vy Tb4b4b4= Te6edf3bodiesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4.Te6edf3vy
Tb4b4b4}
Tb4b4b4}
Te6edf3outTb4b4b4.Te6edf3Iterations Tb4b4b4= Te6edf3iters
Tff7b72return Te6edf3out
Tb4b4b4}

Tff7b72func Te6edf3pickIterationsTb4b4b4(Te6edf3n Tffa657intTb4b4b4) Tffa657int Tb4b4b4{
Tff7b72if Te6edf3n Tff7b72>= T79c0ff1500 Tb4b4b4{
Tff7b72return T79c0ff45
Tb4b4b4}
Tff7b72if Te6edf3n Tff7b72>= T79c0ff600 Tb4b4b4{
Tff7b72return T79c0ff70
Tb4b4b4}
Tff7b72if Te6edf3n Tff7b72>= T79c0ff200 Tb4b4b4{
Tff7b72return T79c0ff100
Tb4b4b4}
Tff7b72return T79c0ff140
Tb4b4b4}


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────